home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / gl_mesh.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  8KB  |  361 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // gl_mesh.c: triangle model functions
  21.  
  22. #include "quakedef.h"
  23.  
  24. /*
  25. =================================================================
  26.  
  27. ALIAS MODEL DISPLAY LIST GENERATION
  28.  
  29. =================================================================
  30. */
  31.  
  32. model_t        *aliasmodel;
  33. aliashdr_t    *paliashdr;
  34.  
  35. qboolean    used[8192];
  36.  
  37. // the command list holds counts and s/t values that are valid for
  38. // every frame
  39. int        commands[8192];
  40. int        numcommands;
  41.  
  42. // all frames will have their vertexes rearranged and expanded
  43. // so they are in the order expected by the command list
  44. int        vertexorder[8192];
  45. int        numorder;
  46.  
  47. int        allverts, alltris;
  48.  
  49. int        stripverts[128];
  50. int        striptris[128];
  51. int        stripcount;
  52.  
  53. /*
  54. ================
  55. StripLength
  56. ================
  57. */
  58. int    StripLength (int starttri, int startv)
  59. {
  60.     int            m1, m2;
  61.     int            j;
  62.     mtriangle_t    *last, *check;
  63.     int            k;
  64.  
  65.     used[starttri] = 2;
  66.  
  67.     last = &triangles[starttri];
  68.  
  69.     stripverts[0] = last->vertindex[(startv)%3];
  70.     stripverts[1] = last->vertindex[(startv+1)%3];
  71.     stripverts[2] = last->vertindex[(startv+2)%3];
  72.  
  73.     striptris[0] = starttri;
  74.     stripcount = 1;
  75.  
  76.     m1 = last->vertindex[(startv+2)%3];
  77.     m2 = last->vertindex[(startv+1)%3];
  78.  
  79.     // look for a matching triangle
  80. nexttri:
  81.     for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
  82.     {
  83.         if (check->facesfront != last->facesfront)
  84.             continue;
  85.         for (k=0 ; k<3 ; k++)
  86.         {
  87.             if (check->vertindex[k] != m1)
  88.                 continue;
  89.             if (check->vertindex[ (k+1)%3 ] != m2)
  90.                 continue;
  91.  
  92.             // this is the next part of the fan
  93.  
  94.             // if we can't use this triangle, this tristrip is done
  95.             if (used[j])
  96.                 goto done;
  97.  
  98.             // the new edge
  99.             if (stripcount & 1)
  100.                 m2 = check->vertindex[ (k+2)%3 ];
  101.             else
  102.                 m1 = check->vertindex[ (k+2)%3 ];
  103.  
  104.             stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
  105.             striptris[stripcount] = j;
  106.             stripcount++;
  107.  
  108.             used[j] = 2;
  109.             goto nexttri;
  110.         }
  111.     }
  112. done:
  113.  
  114.     // clear the temp used flags
  115.     for (j=starttri+1 ; j<pheader->numtris ; j++)
  116.         if (used[j] == 2)
  117.             used[j] = 0;
  118.  
  119.     return stripcount;
  120. }
  121.  
  122. /*
  123. ===========
  124. FanLength
  125. ===========
  126. */
  127. int    FanLength (int starttri, int startv)
  128. {
  129.     int        m1, m2;
  130.     int        j;
  131.     mtriangle_t    *last, *check;
  132.     int        k;
  133.  
  134.     used[starttri] = 2;
  135.  
  136.     last = &triangles[starttri];
  137.  
  138.     stripverts[0] = last->vertindex[(startv)%3];
  139.     stripverts[1] = last->vertindex[(startv+1)%3];
  140.     stripverts[2] = last->vertindex[(startv+2)%3];
  141.  
  142.     striptris[0] = starttri;
  143.     stripcount = 1;
  144.  
  145.     m1 = last->vertindex[(startv+0)%3];
  146.     m2 = last->vertindex[(startv+2)%3];
  147.  
  148.  
  149.     // look for a matching triangle
  150. nexttri:
  151.     for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
  152.     {
  153.         if (check->facesfront != last->facesfront)
  154.             continue;
  155.         for (k=0 ; k<3 ; k++)
  156.         {
  157.             if (check->vertindex[k] != m1)
  158.                 continue;
  159.             if (check->vertindex[ (k+1)%3 ] != m2)
  160.                 continue;
  161.  
  162.             // this is the next part of the fan
  163.  
  164.             // if we can't use this triangle, this tristrip is done
  165.             if (used[j])
  166.                 goto done;
  167.  
  168.             // the new edge
  169.             m2 = check->vertindex[ (k+2)%3 ];
  170.  
  171.             stripverts[stripcount+2] = m2;
  172.             striptris[stripcount] = j;
  173.             stripcount++;
  174.  
  175.             used[j] = 2;
  176.             goto nexttri;
  177.         }
  178.     }
  179. done:
  180.  
  181.     // clear the temp used flags
  182.     for (j=starttri+1 ; j<pheader->numtris ; j++)
  183.         if (used[j] == 2)
  184.             used[j] = 0;
  185.  
  186.     return stripcount;
  187. }
  188.  
  189.  
  190. /*
  191. ================
  192. BuildTris
  193.  
  194. Generate a list of trifans or strips
  195. for the model, which holds for all frames
  196. ================
  197. */
  198. void BuildTris (void)
  199. {
  200.     int        i, j, k;
  201.     int        startv;
  202.     mtriangle_t    *last, *check;
  203.     int        m1, m2;
  204.     int        striplength;
  205.     trivertx_t    *v;
  206.     mtriangle_t *tv;
  207.     float    s, t;
  208.     int        index;
  209.     int        len, bestlen, besttype;
  210.     int        bestverts[1024];
  211.     int        besttris[1024];
  212.     int        type;
  213.  
  214.     //
  215.     // build tristrips
  216.     //
  217.     numorder = 0;
  218.     numcommands = 0;
  219.     memset (used, 0, sizeof(used));
  220.     for (i=0 ; i<pheader->numtris ; i++)
  221.     {
  222.         // pick an unused triangle and start the trifan
  223.         if (used[i])
  224.             continue;
  225.  
  226.         bestlen = 0;
  227.         for (type = 0 ; type < 2 ; type++)
  228. //    type = 1;
  229.         {
  230.             for (startv =0 ; startv < 3 ; startv++)
  231.             {
  232.                 if (type == 1)
  233.                     len = StripLength (i, startv);
  234.                 else
  235.                     len = FanLength (i, startv);
  236.                 if (len > bestlen)
  237.                 {
  238.                     besttype = type;
  239.                     bestlen = len;
  240.                     for (j=0 ; j<bestlen+2 ; j++)
  241.                         bestverts[j] = stripverts[j];
  242.                     for (j=0 ; j<bestlen ; j++)
  243.                         besttris[j] = striptris[j];
  244.                 }
  245.             }
  246.         }
  247.  
  248.         // mark the tris on the best strip as used
  249.         for (j=0 ; j<bestlen ; j++)
  250.             used[besttris[j]] = 1;
  251.  
  252.         if (besttype == 1)
  253.             commands[numcommands++] = (bestlen+2);
  254.         else
  255.             commands[numcommands++] = -(bestlen+2);
  256.  
  257.         for (j=0 ; j<bestlen+2 ; j++)
  258.         {
  259.             // emit a vertex into the reorder buffer
  260.             k = bestverts[j];
  261.             vertexorder[numorder++] = k;
  262.  
  263.             // emit s/t coords into the commands stream
  264.             s = stverts[k].s;
  265.             t = stverts[k].t;
  266.             if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
  267.                 s += pheader->skinwidth / 2;    // on back side
  268.             s = (s + 0.5) / pheader->skinwidth;
  269.             t = (t + 0.5) / pheader->skinheight;
  270.  
  271.             *(float *)&commands[numcommands++] = s;
  272.             *(float *)&commands[numcommands++] = t;
  273.         }
  274.     }
  275.  
  276.     commands[numcommands++] = 0;        // end of list marker
  277.  
  278.     Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
  279.  
  280.     allverts += numorder;
  281.     alltris += pheader->numtris;
  282. }
  283.  
  284.  
  285. /*
  286. ================
  287. GL_MakeAliasModelDisplayLists
  288. ================
  289. */
  290. void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr)
  291. {
  292.     int        i, j;
  293.     maliasgroup_t    *paliasgroup;
  294.     int            *cmds;
  295.     trivertx_t    *verts;
  296.     char    cache[MAX_QPATH], fullpath[MAX_OSPATH], *c;
  297.     FILE    *f;
  298.     int        len;
  299.     byte    *data;
  300.  
  301.     aliasmodel = m;
  302.     paliashdr = hdr;    // (aliashdr_t *)Mod_Extradata (m);
  303.  
  304.     //
  305.     // look for a cached version
  306.     //
  307.     strcpy (cache, "glquake/");
  308.     COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/"));
  309.     strcat (cache, ".ms2");
  310.  
  311.     COM_FOpenFile (cache, &f);    
  312.     if (f)
  313.     {
  314.         fread (&numcommands, 4, 1, f);
  315.         fread (&numorder, 4, 1, f);
  316.         fread (&commands, numcommands * sizeof(commands[0]), 1, f);
  317.         fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  318.         fclose (f);
  319.     }
  320.     else
  321.     {
  322.         //
  323.         // build it from scratch
  324.         //
  325.         Con_Printf ("meshing %s...\n",m->name);
  326.  
  327.         BuildTris ();        // trifans or lists
  328.  
  329.         //
  330.         // save out the cached version
  331.         //
  332.         sprintf (fullpath, "%s/%s", com_gamedir, cache);
  333.         f = fopen (fullpath, "wb");
  334.         if (f)
  335.         {
  336.             fwrite (&numcommands, 4, 1, f);
  337.             fwrite (&numorder, 4, 1, f);
  338.             fwrite (&commands, numcommands * sizeof(commands[0]), 1, f);
  339.             fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f);
  340.             fclose (f);
  341.         }
  342.     }
  343.  
  344.  
  345.     // save the data out
  346.  
  347.     paliashdr->poseverts = numorder;
  348.  
  349.     cmds = Hunk_Alloc (numcommands * 4);
  350.     paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
  351.     memcpy (cmds, commands, numcommands * 4);
  352.  
  353.     verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts 
  354.         * sizeof(trivertx_t) );
  355.     paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
  356.     for (i=0 ; i<paliashdr->numposes ; i++)
  357.         for (j=0 ; j<numorder ; j++)
  358.             *verts++ = poseverts[i][vertexorder[j]];
  359. }
  360.  
  361.